package com.jiuqi.bi.metagraph.server.graph.rest;

import com.jiuqi.bi.metagraph.server.graph.MetaGraphUtil;
import com.jiuqi.bi.metagraph.server.graph.bean.CorrelationTableBean;
import com.jiuqi.bi.metagraph.server.graph.bean.EntityBean;
import com.jiuqi.bi.metagraph.server.graph.manager.MetaGraphManager;
import com.jiuqi.bi.metagraph.server.graph.query.GraphBuffer;
import com.jiuqi.bi.metagraph.server.ualog.MetagraphUALModule;
import com.jiuqi.bi.ualog.UALInfo;
import com.jiuqi.bi.ualog.UALType;
import com.jiuqi.bi.ualog.UALogger;
import com.jiuqi.bi.ualog.module.IUALModule;
import com.jiuqi.bi.util.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.json.JSONObject;
import org.restlet.data.Form;
import org.restlet.data.Status;
import org.restlet.ext.servlet.ServletUtils;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.ResourceException;
import org.restlet.resource.ServerResource;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class GraphCorrelationExportResource extends ServerResource {


    /**
     * 获取前端参数：查询节点的guid、选择的关联关系类型、输出表单名称、选择的实体类型、输入的实体查询名称
     * keyword               一定不为空
     * relationString        一定不为空（若用户未选择，默认影响——out）
     * excelName             一定不为空
     * types                 可能为空
     * filterString          可能为空
     */
    @Override
    protected Representation post(Representation representation) throws ResourceException {
        try {
            HttpServletResponse response = ServletUtils.getResponse(getResponse());
            Form form = new Form(representation);
            String keyword = form.getFirstValue("keyword");
            String relationString = URLDecoder.decode(form.getFirstValue("relationString"), StandardCharsets.UTF_8.name());
            String types = URLDecoder.decode(form.getFirstValue("types"), StandardCharsets.UTF_8.name());
            String filterString = URLDecoder.decode(form.getFirstValue("filterString"), StandardCharsets.UTF_8.name());

            //准备日志内容数据
            MetaGraphManager metaGraphManager = new MetaGraphManager();
            EntityBean keyEntity = metaGraphManager.getEntity(keyword);
            Boolean isBlood = relationString.equals("in");
            Boolean isUseTypeFilter = StringUtils.isNotEmpty(types);
            Boolean isUseStringFilter = StringUtils.isNotEmpty(filterString);

            if (!MetaGraphUtil.isOpenGraph()) {
                throw new Exception("系统未开启图谱分析，不允许该操作！");
            }

            List<CorrelationTableBean> correlationTableBeans = GraphBuffer.relatedData(keyword, isBlood, types, filterString);

            //导出数据
            exportProcessor(correlationTableBeans, response);

            //记录操作日志
            String relationType = isBlood ? "血缘" : "影响";
            StringBuffer ualData = new StringBuffer();
            ualData.append(String.format("对 [%s] 图谱实体进行 [%s] 关系查询", keyEntity.getTitle(), relationType));
            ualData.append(isUseTypeFilter ? "，进行实体类型过滤" : "");
            ualData.append(isUseStringFilter ? "，进行实体名称模糊匹配" : "");
            ualData.append("后导出查询结果。");

            String ualDesc = "导出[" + keyEntity.getTitle() + "]相关性查询结果";
            UALInfo ualInfo = new UALInfo(UALType.EXPORT, keyEntity.getGuid(), keyEntity.getTitle(), ualData.toString(), ualDesc.toString());
            new UALogger(MetagraphUALModule.getInstance()).info(ualInfo);

            return new StringRepresentation(new JSONObject().toString());

        } catch (Exception e) {
            throw new ResourceException(Status.SERVER_ERROR_INTERNAL, e.getMessage());
        }
    }

    /**
     * 导出处理器
     *
     * @param correlationTableBeans 当前过滤完成的相关性查询信息
     * @return
     * @throws IOException
     */
    private void exportProcessor(List<CorrelationTableBean> correlationTableBeans, HttpServletResponse response) throws IOException {
        //创建Excel的文档对象
        HSSFWorkbook wb = new HSSFWorkbook();
        //创建Excel表单
        HSSFSheet sheet = wb.createSheet("sheet1");

        //创建表单的第二行，即标题行
        HSSFRow row0 = sheet.createRow(0);

        row0.setHeight((short) (25 * 20));

        for (int i = 0; i < 5; i++) {
            //实体路径列 和 关系路径列 加宽处理
            if (i == 3 || i == 4) {
                sheet.setColumnWidth(i, 450 * 35);
            } else {
                sheet.setColumnWidth(i, 150 * 35);
            }
        }

        //准备数据：标题行
        List<String> titleList = new ArrayList<>(5);
        titleList.add("标题");
        titleList.add("标识");
        titleList.add("类型");
        titleList.add("路径");
        titleList.add("关联关系路径");
        //把标题数据赋给第0行
        AtomicInteger num0 = new AtomicInteger(0);
        titleList.stream().forEach(i -> {
            row0.createCell(num0.get()).setCellValue(i);
            num0.getAndIncrement();
        });
        //准备数据：具体内容行——correlationTableBeans
        //数据按行赋值
        AtomicInteger num1 = new AtomicInteger();
        correlationTableBeans.stream().forEach(i -> {
            HSSFRow currentRow = sheet.createRow(num1.get() + 1);
            currentRow.setHeight((short) (25 * 20));
            currentRow.createCell(0).setCellValue(i.getTitle());
            currentRow.createCell(1).setCellValue(i.getName());
            currentRow.createCell(2).setCellValue(i.getType());
            currentRow.createCell(3).setCellValue(i.getPath());

            AtomicInteger num = new AtomicInteger(1);
            List<String> transitCollection = new ArrayList<>();
            i.getEntityBeanPath().stream().forEach(it -> {
                String transitString = "";
                if (num.get() == i.getEntityBeanPath().size()) {
                    transitString += it.getTitle();
                } else {
                    transitString += it.getTitle() + " --> ";
                }
                num.getAndIncrement();
                transitCollection.add(transitString);
            });
            String reduce = transitCollection.stream().reduce("", (s, s1) -> s + s1);
            currentRow.createCell(4).setCellValue(reduce);

            num1.getAndIncrement();
        });

        try {
            ServletOutputStream stream = null;
            try {
                response.setContentType("application/octet-stream;charset=UTF-8;");
                response.addHeader("Content-Disposition", "attachment");
                response.setHeader("CacheControl", "Private");

                stream = response.getOutputStream();
                wb.write(stream);
                stream.flush();
            } finally {
                if (stream != null) {
                    stream.close();
                }

            }
        } finally {
            wb.close();
        }
    }

}
